<?php
/**
 * Created by PhpStorm.
 * User: peter
 * Date: 2018/10/19
 * Time: 下午4:56
 */

namespace app\activity\controller;


use app\model\AccountCapitalFlow;
use app\model\ActivityOrder;
use app\model\ActivityOrderAttach;
use app\model\ActivityOrderRefund;
use app\model\Bill;
use app\model\RechargeOrder;
use EasyWeChat\Factory;
use EasyWeChat\Kernel\Support\XML;
use extend\Functions;
use extend\STATUS_CODE;
use think\Controller;
use think\facade\Env;
use think\facade\Log;
use think\Request;

class PayNotify extends Controller
{
    /**
     * @purpose 余额充值微信异步回调
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function rechargeByWeChatAsync () {

        $payment  = Factory::payment(config('wechat.payment.official_account'));
        $response = $payment->handlePaidNotify(function ($message, $fail) {
            $order_no  = $message['out_trade_no'];
            $return_code = $message['return_code'];
            if (strtolower($return_code) === 'success') {
                $trade_no     = $message['transaction_id'];
                $pay_money    = $message['total_fee'];
                $order        = new RechargeOrder();
                $member       = new \app\model\Member();
                $order->startTrans();
                $order_info   = $order
                    ->lock(true)
                    ->where('order_no', $order_no)
                    ->field('id,uid,quota,status,order_no')
                    ->find();
                $member_info = $member
                    ->where('uid', $order_info->uid)
                    ->field('uid,balance,frozen')
                    ->find();
                if (!$order_info) {
                    return $fail('订单不存在');
                }
                if ($order_info->status === 99) {
                    return true;
                }
                if ($order_info->status !== 1) {
                    return $fail('订单状态错误!');
                }
                $order_result = $order
                    ->isUpdate(true)
                    ->save(
                        [
                            'status' => 99,
                            'pay_at' => time(),
                            'pay_no' => $trade_no,
                            'pay_method' => 1,
                            'pay_money' => $pay_money,
                        ],
                        ['id' => $order_info->id]);
                // 增加账户余额
                $member_result = $member
                    ->where('uid', $order_info->uid)
                    ->setInc('balance', $order_info->quota);
                // 记录账户资金流水
                $account_capital_flow = AccountCapitalFlow::M()
                ->data([
                    'uid' => $order_info->uid,
                    'quota' => $order_info->quota,
                    'type' => 1,
                    'balance' => $order_info->quota + ($member_info->balance - $member_info->frozen),
                    'descriptions' => '充值余额-微信'
                ])
                ->save();
                // 记录支付账单
                Bill::addToBill(
                    $order_info->uid,
                    5,
                    $order_info->order_no,
                    $pay_money,
                    1,
                    '余额充值'
                );
                if ($order_result && $member_result && $account_capital_flow) {
                    $order->commit();
                    return true;
                }
                // 记录账户资金流水
                $order->rollback();
                return $fail('fail');
            }
            return $fail('fail');
        });
        $response->send();
    }

    /**
     * @purpose 余额充值支付宝异步回调
     * @param Request $request
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function rechargeByAliPayAsync (Request $request) {


        // 获取订单号
        $order_no  = $request->post('out_trade_no');
        // 获取第三方支付单号
        $trade_no  = $request->post('trade_no');
        // 获取交易状态
        $trade_status = $request->post('trade_status');
        // 订单支付金额
        $total_amount = $request->post('total_amount');
//        $send_pay_date = $request->post('send_pay_date');

        // 支付宝支付
        include Env::get('root_path'). 'extend/alipay/AopSdk.php';
        include Env::get('root_path'). 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
        $aop                            = new \AopClient();
        $aop->gatewayUrl                = 'https://openapi.alipay.com/gateway.do';
        $aop->appId                     = config('alipay.app.appid');
        $aop->rsaPrivateKey             = config('alipay.app.private_key');
        $aop->format                    = "json";
        $aop->charset                   = "UTF-8";
        $aop->signType                  = "RSA";
        $aop->alipayrsaPublicKey        = config('alipay.app.public_key');
        $flag = $aop->rsaCheckV1($request->post(), null, 'RSA');

        if ($flag) {
            // 交易支付成功
            if ($trade_status === 'TRADE_SUCCESS') {
                $pay_money    = (int) ($total_amount * 100);
                $order        = new RechargeOrder();
                $member       = new \app\model\Member();
                $order->startTrans();
                $order_info   = $order
                    ->lock(true)
                    ->where('order_no', $order_no)
                    ->field('id,uid,quota,status,order_no')
                    ->find();
                if (!$order_info) {
                    $order->rollback();
                    exit('fail');
                }
                if ($order_info->status === 99) {
                    $order->rollback();
                    exit('success');
                }
                if ($order_info->status !== 1) {
                    $order->rollback();
                    exit('fail');
                }
                $member_info = $member
                    ->where('uid', $order_info->uid)
                    ->field('uid,balance,frozen')
                    ->find();
                $order_result = $order
                    ->isUpdate(true)
                    ->save(
                        [
                            'status' => 99,
                            'pay_at' => time(),
                            'pay_no' => $trade_no,
                            'pay_method' => 1,
                            'pay_money' => $pay_money,
                        ],
                        ['id' => $order_info->id]);
                // 增加账户余额
                $member_result = $member
                    ->where('uid', $order_info->uid)
                    ->setInc('balance', $order_info->quota);
                // 记录账户资金流水
                $account_capital_flow = AccountCapitalFlow::M()
                    ->data([
                        'uid' => $order_info->uid,
                        'quota' => $order_info->quota,
                        'balance' => $order_info->quota + ($member_info->balance - $member_info->frozen),
                        'type' => 1,
                        'descriptions' => '余额充值-支付宝'
                    ])
                    ->save();
                // 记录支付账单
                Bill::addToBill(
                    $order_info->uid,
                    5,
                    $order_info->order_no,
                    $pay_money,
                    2,
                    '余额充值'
                );
                if ($order_result && $member_result && $account_capital_flow) {
                    $order->commit();
                    exit('success');
                }
                // 记录账户资金流水
                $order->rollback();
                exit('fail');
            }
        }
    }
    /**
     * @purpose 微信退款回调
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function wechatRefundAsync() {
        $app  = Factory::payment(config('wechat.payment.official_account'));
        $response = $app->handleRefundedNotify(function ($message, $reqInfo ,$fail) {

            $refund_status   = $reqInfo['refund_status'];
            if (strtolower($refund_status) === 'success') {
                $refund_no = $reqInfo['out_refund_no'];
                $order_refund = new ActivityOrderRefund();
                $order        = new ActivityOrder();
                $order_attach = new ActivityOrderAttach();
                $order_refund->startTrans();
                $order_refund_info = $order_refund
                    ->lock(true)
                    ->with(['activity' => function($query){
                        $query->field('id,title');
                    }])
                    ->where('refund_no', $refund_no)
                    ->field('id,order_id,uid,activity_id,order_attach_id,status,refund_money,refund_reason')
                    ->find();
                if (!$order_refund_info) {
                    $order_refund->rollback();
                    return $fail('Order is not find!');
                }
                if ($order_refund_info->status !== 2) {
                    $order_refund->rollback();
                    return true;
                }
                // 更新退款订单状态
                $order_refund_result = $order_refund
                    ->isUpdate(true)
                    ->save(['status' => 3, 'success_at' => strtotime($reqInfo['success_time'])], ['id' => $order_refund_info->id]);
                // 更新订单附表状态
                $order_attach_result = $order_attach
                    ->where('id', 'in', $order_refund_info->order_attach_id)
                    ->update(['status' => 3]);
                // 检测订单是否全部退款
                $order_result = true;
                if ($order_attach->where([
                    ['order_id', '=', $order_refund_info->order_id],
                    ['status', ['=', 4],['=', 5], ['=', 99], 'or']
                ])->count(1) < 1) {
                    $order_result = $order
                        ->isUpdate(true)
                        ->save([
                            'status' => 3
                        ], ['id' => $order_refund_info->order_id]);
                }// 记录账单活动支付账单
                Bill::addToBill(
                    $order_refund_info->uid,
                    2,
                    $refund_no,
                    $order_refund_info->refund_money,
                    0,
                    '活动退款: 【'.$order_refund_info->activity->title.'】,退款原因【'.$order_refund_info->refund_reason.'】'
                );
                if ($order_refund_result &&
                    $order_attach_result &&
                    $order_result) {
                    $order_refund->commit();
                    return true;
                }
                $order_refund->rollback();
                return $fail('fail');
            }
            return $fail('fail');
        });

        $response->send();
    }

    /**
     * @purpose 支付宝活动支付异步回调
     * @param Request $request
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function activityAliPayAsync (Request $request)
    {

        // 获取订单号
        $order_no  = $request->post('out_trade_no');
        // 获取第三方支付单号
        $trade_no  = $request->post('trade_no');
        // 获取交易状态
        $trade_status = $request->post('trade_status');
        // 订单支付金额
        $total_amount = $request->post('total_amount');
//        $send_pay_date = $request->post('send_pay_date');

        // 支付宝支付
        include Env::get('root_path'). 'extend/alipay/AopSdk.php';
        include Env::get('root_path'). 'extend/alipay/aop/request/AlipayTradeAppPayRequest.php';
        $aop                            = new \AopClient();
        $aop->gatewayUrl                = 'https://openapi.alipay.com/gateway.do';
        $aop->appId                     = config('alipay.app.appid');
        $aop->rsaPrivateKey             = config('alipay.app.private_key');
        $aop->format                    = "json";
        $aop->charset                   = "UTF-8";
        $aop->signType                  = "RSA";
        $aop->alipayrsaPublicKey        = config('alipay.app.public_key');
        $flag = $aop->rsaCheckV1($request->post(), null, 'RSA');

        if ($flag) {
            // 交易支付成功
            if ($trade_status === 'TRADE_SUCCESS') {
                $order = new ActivityOrder();
                $order_attach = new ActivityOrderAttach();
                $order_info = $order
                    ->lock(true)
                    ->with(['activity' => function($query) {
                        $query->field('id,title');
                    }])
                    ->where([
                        'order_no' => $order_no
                    ])
                    ->field('id,uid,activity_id,status,order_no,pay_voucher,create_at')
                    ->find();
                if (!$order_info) {
                    $order->rollback();
                    exit('order is not find...!');
                }
                if ($order_info->status === 99) {
                    $order->rollback();
                    exit('success');
                }

                $update_data               = [];
                $update_data['status']     = 99;
                $update_data['pay_time']   = time(); // strtotime($send_pay_date);
                $update_data['pay_money']  = $total_amount * 100;
                $update_data['pay_method'] = 3;
                $update_data['pay_no']     = $trade_no;
                // 更新订单状态
                $order
                    ->isUpdate(true)
                    ->save($update_data, ['id' => $order_info->id]);
                // 更新订单附表状态
                $order_attach
                    ->isUpdate(true)
                    ->save(['status' => 99], ['order_id' => $order_info->id, 'status' => 1]);
                // 记录账单活动支付账单
                Bill::addToBill(
                    $order_info->uid,
                    1,
                    $order_no,
                    $total_amount * 100,
                    3,
                    '报名活动: 【'.$order_info->activity->title.'】'
                );
                $order->commit();
                exit('success');
            }
            exit('fail');
        } else {
            exit('fail');
        }
    }
    /**
     * @throws \EasyWeChat\Kernel\Exceptions\Exception
     */
    public function wechatPayAsync()
    {
        $payment  = Factory::payment(config('wechat.payment.official_account'));
        $response = $payment->handlePaidNotify(function ($message, $fail) {
            $pay_voucher  = $message['out_trade_no'];
            $pay_voucher = explode('-', $pay_voucher);
            $order_no = $pay_voucher[0];
            $return_code = $message['return_code'];
            if (strtolower($return_code) === 'success') {
                $trade_no     = $message['transaction_id'];
                $pay_money    = $message['total_fee'];
                $order        = new ActivityOrder();
                $order_attach = new ActivityOrderAttach();
                $order->startTrans();
                $order_info   = $order
                    ->lock(true)
                    ->with(['activity' => function($query) {
                        $query->field('id,title');
                    }])
                    ->where('order_no', $order_no)
                    ->field('id,uid,activity_id,status,order_no,group_stage_id')
                    ->find();
                if (!$order_info) {
                    return $fail('订单不存在');
                }
                if ($order_info->status === 99) {
                    return true;
                }
                if ($order_info->status !== 1) {
                    return $fail('订单状态错误!');
                }
                $order_result = $order
                    ->isUpdate(true)
                    ->save(
                        [
                            'status' => 99,
                            'pay_time' => time(),
                            'pay_no' => $trade_no,
                            'pay_method' => 1,
                            'pay_money' => $pay_money,
                        ],
                        ['id' => $order_info->id]);
                $order_attach_result = $order_attach
                    ->isUpdate(true)
                    ->save(
                        ['status' => 99],
                        ['status' => 1, 'order_id' => $order_info->id]
                    );
                // 记录账单活动支付账单
                Bill::addToBill(
                    $order_info->uid,
                    1,
                    $order_info->order_no,
                    $pay_money,
                    1,
                    '报名活动: 【'.$order_info->activity->title.'】'
                );
                if ($order_attach_result && $order_result) {
                    $order->commit();
                    return true;
                }
                $order->rollback();
                return $fail('fail');
            }
            return $fail('fail');
        });
        $response->send();
    }
}